library(shiny)
library(shinythemes)
library(shinyAce)
library(DT)

# 加载配置件
get_config <- function() {
  source("config/general_config.R")
  data.frame(
    标题 = sapply(plot_examples_config, function(x) x$title),
    描述 = sapply(plot_examples_config, function(x) x$description),
    stringsAsFactors = FALSE
  )
}
get_config()

# UI定义
ui <- fluidPage(
  theme = shinytheme("flatly"),
  titlePanel("R绘图代码展示"),
  fluidRow(
    column(3,
      wellPanel(
        DTOutput("examples_table")
      )
    ),
    column(9,
      fluidRow(
        column(6,
          div(style = "height: 80vh;",
            aceEditor("code", value = "", mode = "r", theme = "monokai",
                     height = "calc(100% - 50px)", fontSize = 14),
            div(style = "margin-top: 10px;",
              actionButton("run_code", "运行代码", class = "btn-primary")
            )
          )
        ),
        column(6,
          div(style = "height: 80vh; overflow-y: auto;",
            plotOutput("plot", height = "600px")
          )
        )
      )
    )
  )
)

# 服务器逻辑
server <- function(input, output, session) {
  # 监听plots文件夹变化
  plots_dir_monitor <- reactivePoll(1000, session,
    checkFunc = function() {
      # 获取plots文件夹中所有文件的最后修改时间和文件列表
      files <- list.files("plots", pattern = "\\.R$", full.names = TRUE)
      if (length(files) == 0) return(NULL)
      # 返回文件列表和最后修改时间的组合字符串
      paste(paste(files, collapse = ";"), max(file.info(files)$mtime))
    },
    valueFunc = function() {
      # 重新加载配置
      get_config()
    }
  )
  
  # 使用响应式数据框
  examples_df <- reactive({
    plots_dir_monitor()
  })
  # 从URL参数获取示例ID
  observe({
    query <- parseQueryString(session$clientData$url_search)
    if (!is.null(query$example)) {
      # 查找匹配的示例索引
      example_index <- which(sapply(plot_examples_config, function(x) x$url_id == query$example))
      if (length(example_index) > 0) {
        # 更新表格选择
        dataTableProxy('examples_table') %>% selectRows(example_index)
      }
    }
  })
  # 渲染示例表格
  output$examples_table <- renderDT({
    datatable(
      examples_df(),
      selection = 'single',
      options = list(
        pageLength = 5,
        dom = 'ftp', 
        scrollY = "60vh",
        autoWidth = FALSE,  # 禁用自动宽度调整
        scrollX = TRUE,     # 启用水平滚动
        language = list(
          search = "搜索:",
          paginate = list(previous = "上一页", `next` = "下一页")
        ),
        columnDefs = list(
          list(width = '150px', targets = 0, className = 'dt-head-center dt-body-left'), 
          list(width = '300px', targets = 1, className = 'dt-head-center dt-body-left')  
        )
      ),
      class = 'cell-border stripe',  # 添加表格样式
      rownames = FALSE              # 隐藏行名称以节省空间
    )
  })

  # 存储当前是否是首次加载的标志
  first_load <- reactiveVal(TRUE)
  
  # 根据选择加载对应的绘图代码
  observeEvent(input$examples_table_rows_selected, {
    req(input$examples_table_rows_selected)
    selected_example <- plot_examples_config[[input$examples_table_rows_selected]]
    code_file <- file.path("plots", selected_example$file)
    code_content <- readLines(code_file, warn = FALSE)
    updateAceEditor(session, "code", value = paste(code_content, collapse = "\n"))
    
    # 首次加载时自动运行代码
    if (first_load()) {
      first_load(FALSE)
      # 更新URL
      updateQueryString(paste0("?example=", selected_example$url_id))
    }
  })
  
  # 渲染绘图
  output$plot <- renderPlot({
    # 触发条件：首次加载或点击运行按钮
    req(input$code)
    req(first_load() || input$run_code)
    
    tryCatch({
      eval(parse(text = input$code))
    }, error = function(e) {
      plot.new()
      text(0.5, 0.5, paste("Error:", e$message), col = "red")
    })
  })
}

shinyApp(ui = ui, server = server, options = list(port = 28888))